home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / Terminal 2.2 / Project / Sources / CisB.c < prev    next >
Text File  |  1992-01-17  |  24KB  |  1,053 lines

  1. /*
  2.     Terminal 2.2
  3.     "CisB.c"
  4. */
  5.  
  6. #ifdef THINK_C
  7. #include "MacHeaders"
  8. #endif
  9. #ifdef applec
  10. #pragma load ":(Objects):MacHeadersMPW"
  11. #pragma segment CisB
  12. #endif
  13.  
  14. #include "Text.h"
  15. #include "Main.h"
  16. #include "CisB.h"
  17. #include "Strings.h"
  18. #include "Utilities.h"
  19. #include "CancelDialog.h"
  20. #include "Port.h"
  21. #include "MacBinary.h"
  22. #include "CRC.h"
  23.  
  24. #define ETX            0x03
  25. #define DLE         0x10
  26. #define XON            0x11
  27. #define XOFF        0x13
  28. #define NAK            0x15
  29. #define ESC            0x1B
  30.  
  31. #define MAXBUFSIZE    1032    /* Largest data block we can handle */
  32. #define MAXSA        2        /* Maximum number of waiting packets */
  33. #define DEFWS        1        /* I can send 2 packets ahead */
  34. #define DEFWR        1        /* I can receive send ahead packets */
  35. #define DEFBS        8        /* I can handle 1024 bytes */
  36. #define DEFCM        1        /* I can handle CRC */
  37. #define DEFDQ        1        /* I can handle non-quoted NUL */
  38. #define DEFBUFSIZE    511        /* Default data block */
  39. #define MAXERRORS    10        /* Maximal number of errors allowed */
  40. #define MAXABORT    3        /* Max errors if aborting */
  41. #define MAXTIME        10        /* Timeout (seconds) */
  42. #define ENQDELAY    2        /* Before answering ENQ (seconds) */
  43.  
  44. #define CLOSER        if (Vers) BinCloseRead(); else FSClose(ref)
  45. #define CLOSEW        if (Vers) BinCloseWrite();\
  46.                     else { FSClose(ref); FlushVol(0, volume); }
  47. #define GETEOF        if (Vers) BinGetEOF(&Eof); else GetEOF(ref,&Eof)
  48. #define OPENR(v,d,n)    (Vers ? BinOpenRead(v,d,n) : OpenFile(v,d,n,&ref))
  49. #define READ(c,b)    (Vers ? BinRead(&c,b) : FSRead(ref,&c,b))
  50. #define TIME        ((Eof && Mark) ? ((Time-Ctime)*(Eof-Mark))/Mark : 0)
  51. #define WRITE(c,b)    (Vers ? BinWrite(&c,b) : FSWrite(ref,&c,b))
  52. #define MIN(a,b)    (((a) < (b)) ? (a) : (b))
  53.  
  54. typedef struct {
  55.     short seq;                /* Sequence number */
  56.     short num;                /* Number of data bytes */
  57.     Byte buf[MAXBUFSIZE];    /* Actual data */
  58. } PACKET;
  59.  
  60. typedef struct {
  61.     Byte ws;                /* Window send */
  62.     Byte wr;                /* Window receive */
  63.     Byte bs;                /* Block size */
  64.     Byte cm;                /* Check method */
  65. } PARM;
  66.  
  67. PACKET SABuf[MAXSA + 1];        /* Send-ahead buffers */
  68. static Byte RBuffer[MAXBUFSIZE];/* Receive buffer */
  69. static PARM His;                /* Other End's Parameters */
  70. static PARM Our;                /* Negotiated Parameters */
  71. static short SeqNum;            /* Block sequence number */
  72. static short BufferSize;        /* Our buffer size */
  73. static short Rsize;                /* Size of receiver buffer */
  74. static short SAMax;                /* Send ahead blocks */
  75. static short AckSA;                /* Which SABuf is waiting for ACK */
  76. static short FillSA;            /* Which SABuf is ready for new data */
  77. static short SAWaiting;            /* Number of SABuf's waiting for ACK */
  78. static Boolean QuickB;            /* TRUE if QuickB in effect */
  79. static Boolean UseCRC;            /* TRUE if CRC in effect */
  80. static Boolean SAEnabled;        /* TRUE if send ahead in effect */
  81. static Boolean Aborting;        /* TRUE if aborting transfer */
  82.  
  83. static Boolean Binary;        /* Binary (or ASCII) */
  84. static long Mark;            /* Current file mark */
  85. static long Eof;            /* Length of file (if known) */
  86. static long Ctime;            /* Current time in (seconds) */
  87. static short Vers;            /* MacBinary version */
  88. static long Blk;            /* Block counter */
  89.  
  90. void SendFailure(Byte);
  91.  
  92. /* ----- Send a byte to the host --------------------------------------- */
  93.  
  94. static void SendByte(Byte ch)
  95. {
  96.     SerialSend(&ch, 1, &Busy);
  97.     while (Busy)
  98.         ;
  99. }
  100.  
  101. /* ----- Send a masked byte to the host -------------------------------- */
  102.  
  103. static Byte QuoteTable[] = {
  104.     0, 0, 0, 1, 0, 1, 0, 0,    /* nul soh stx ETX eot ENQ ack bel */
  105.     0, 0, 0, 0, 0, 0, 0, 0,    /* bs  ht  lf  vt  ff  cr  so  si  */
  106.     1, 1, 0, 1, 0, 1, 0, 0,    /* DLE XON dc2 XOF dc4 NAK syn etb */
  107.     0, 0, 0, 0, 0, 0, 0, 0    /* can em  sub esc fs  gs  rs  us  */
  108. };
  109.  
  110. static void SendMaskedByte(register Byte ch)
  111. {
  112.     if (ch < 32 && QuoteTable[ch]) {
  113.         SendByte(DLE);
  114.         SendByte(ch + '@');
  115.     } else
  116.         SendByte(ch);
  117. }
  118.  
  119. /* ----- Send an ACK to the host --------------------------------------- */
  120.  
  121. static void SendACK(register short seqnum)
  122. {
  123.     SendByte(DLE);
  124.     SendByte(seqnum + '0');
  125. }
  126.  
  127. /* ----- Read byte from the host --------------------------------------- */
  128.  
  129. static short ReadByte(register Byte *ch)
  130. {
  131.     register long start;
  132.     register long count;
  133.  
  134.     /* If a character is available don't check for cancel,
  135.     this speeds up reception */
  136.  
  137.     if (!SerialRead(ch, 1)) {
  138.         start = Time;
  139.         do {
  140.             if ((Time - start) > MAXTIME)
  141.                 return TIMEOUT;
  142.             if (!(count = SerialRead(ch, 1)) && CheckCancel())
  143.                 return CANCEL;
  144.         } while (count == 0);
  145.     }
  146.     return FINE;
  147. }
  148.  
  149. /* ----- Read masked byte from the host -------------------------------- */
  150.  
  151. static short ReadMaskedByte(
  152.     register Byte *ch,
  153.     register Boolean *masked)
  154. {
  155.     register short err;
  156.  
  157.     *masked = FALSE;
  158.     if (err = ReadByte(ch))
  159.         return err;
  160.     if (*ch == DLE) {
  161.         if (err = ReadByte(ch))
  162.             return err;
  163.         *masked = TRUE;
  164.         *ch &= 0x1F;
  165.     }
  166.     return err;
  167. }
  168.  
  169. /* ----- Increment Sequence Number ------------------------------------- */
  170.  
  171. static short IncrSeq(register short value)
  172. {
  173.     return (value == 9) ? 0 : value + 1;
  174. }
  175.  
  176. /* ----- Increment Send Ahead ------------------------------------------ */
  177.  
  178. static short IncrSA(register short value)
  179. {
  180.     return (value == MAXSA) ? 0 : value + 1;
  181. }
  182.  
  183. /* ----- Calculate checksum or CRC ------------------------------------- */
  184.  
  185. static unsigned short DoChecksum(
  186.     register Byte ch,
  187.     register unsigned short cksm)
  188. {
  189.     if (QuickB && UseCRC)
  190.         return UpdateCRC(ch, cksm);
  191.     cksm <<= 1;
  192.     if (cksm > 255)
  193.         cksm = (cksm & 0xFF) + 1;
  194.     cksm += ch;
  195.     if (cksm > 255)
  196.         cksm = (cksm & 0xFF) + 1;
  197.     return cksm;
  198. }
  199.  
  200.  
  201. /* ----- Send data to the host ----------------------------------------- */
  202.  
  203. static void SendData(short buffernumber)
  204. {
  205.     register short n;
  206.     register PACKET    *p;
  207.     register Byte b, *q;
  208.     register unsigned short cksm;
  209.  
  210.     p = &SABuf[buffernumber];
  211.     cksm = (QuickB && UseCRC) ? 0xFFFF : 0;
  212.     SendByte(DLE);
  213.     SendByte('B');
  214.     SendByte(b = p->seq + '0');
  215.     cksm = DoChecksum(b, cksm);
  216.     n = p->num;
  217.     q = p->buf;
  218.     while (n--) {
  219.         SendMaskedByte(b = *q++);
  220.         cksm = DoChecksum(b, cksm);
  221.     }
  222.     SendByte(ETX);
  223.     cksm = DoChecksum(ETX, cksm);
  224.     if (QuickB && UseCRC)
  225.         SendMaskedByte((cksm >> 8) & 0xFF);
  226.     SendMaskedByte(cksm & 0xFF);
  227. }
  228.  
  229. /* ----- Restablish syncronism with the remote ------------------------- */
  230.  
  231. enum {
  232.     GETFIRSTDLE,
  233.     GETFIRSTDIGIT,
  234.     GETSECONDDLE,
  235.     GETSECONDDIGIT
  236. };
  237.  
  238. static short ReSync(register Byte *digit)
  239. {
  240.     register short state, err;
  241.     Byte c;
  242.  
  243.     SendByte(ENQ);
  244.     SendByte(ENQ);
  245.     state = GETFIRSTDLE;
  246.     for (;;) {
  247.         if (err = ReadByte(&c))
  248.             return err;
  249.         switch (state) {
  250.             case GETFIRSTDLE:
  251.                 if (c == DLE)
  252.                     state = GETFIRSTDIGIT;
  253.                 break;
  254.             case GETFIRSTDIGIT:
  255.                 if (c >= '0' && c <= '9') {
  256.                     *digit = c;
  257.                     state = GETSECONDDLE;
  258.                 }
  259.                 break;
  260.             case GETSECONDDLE:
  261.                 if (c == DLE)
  262.                     state = GETSECONDDIGIT;
  263.                 break;
  264.             case GETSECONDDIGIT :
  265.                 if (c >='0' && c <='9') {
  266.                     if (*digit == c)
  267.                         return FINE;
  268.                     *digit = c;
  269.                 }
  270.                 state = GETSECONDDLE;
  271.                 break;
  272.         }
  273.     }
  274. }
  275.  
  276. /* ----- Read a packet ------------------------------------------------- */
  277.  
  278. enum {            /* Receive states */
  279.     RGETDLE,
  280.     RGETB,
  281.     RGETSEQ,
  282.     RGETDATA,
  283.     RGETCHECKSUM,
  284.     RSENDACK,
  285.     RTIMEDOUT,
  286.     RSUCCESS
  287. };
  288.  
  289. static short ReadPacket(
  290.     Boolean leadinseen,
  291.     Boolean fromsendpacket)
  292. {
  293.     register short state, err, n;
  294.     register unsigned short cks;
  295.     short nextseq, blocknum, errors, newcks;
  296.     Byte c;
  297.     Boolean masked;
  298.     register Byte *message;    /* Message for progress dialog */
  299.  
  300.     for (n = 0; n < BufferSize; ++n)
  301.         RBuffer[n] = 0;
  302.     nextseq = IncrSeq(SeqNum);
  303.     errors = 0;
  304.     state = leadinseen ? RGETSEQ : RGETDLE;
  305.     for (;;) {
  306.         switch (state) {
  307.             case RGETDLE:    /* Wait for DLE */
  308.                 message = EmptyStr;
  309.                 err = ReadByte(&c);
  310.                 if (CheckCancel())
  311.                     err = CANCEL;
  312.                 switch (err) {
  313.                     case CANCEL:
  314.                         SendFailure('A');
  315.                         return err;
  316.                     case TIMEOUT:
  317.                         message = MyString(STR_P, P_TIMEOUT);
  318.                         state = RTIMEDOUT;
  319.                         break;
  320.                     case FINE:
  321.                         switch (c) {
  322.                             case DLE:
  323.                                 state = RGETB;
  324.                                 break;
  325.                             case ENQ:
  326.                                 state = RSENDACK;
  327.                                 break;
  328.                         }
  329.                 }
  330.                 break;
  331.             case RGETB:        /* Wait for 'B' */
  332.                 message = EmptyStr;
  333.                 err = ReadByte(&c);
  334.                 switch (err) {
  335.                     case TIMEOUT:
  336.                     case CANCEL:
  337.                         message = MyString(STR_P, P_TIMEOUT);
  338.                         state = RTIMEDOUT;
  339.                         break;
  340.                     case FINE:
  341.                         switch (c) {
  342.                             case 'B':
  343.                                 state = RGETSEQ;
  344.                                 break;
  345.                             case ENQ:
  346.                                 state = RSENDACK;
  347.                                 break;
  348.                             default:
  349.                                 state = RGETDLE;
  350.                                 break;
  351.                         }
  352.                 }
  353.                 break;
  354.             case RGETSEQ:    /* Wait for block sequence number */
  355.                 message = EmptyStr;
  356.                 err = ReadByte(&c);
  357.                 switch (err) {
  358.                     case TIMEOUT:
  359.                     case CANCEL:
  360.                         message = MyString(STR_P, P_TIMEOUT);
  361.                         state = RTIMEDOUT;
  362.                         break;
  363.                     case FINE:
  364.                         switch (c) {
  365.                             case ENQ:
  366.                                 state = RSENDACK;
  367.                                 break;
  368.                             default:
  369.                                 cks = (QuickB && UseCRC) ? 0xFFFF : 0;
  370.                                 blocknum = c - '0';
  371.                                 cks = DoChecksum(c, cks);
  372.                                 n = 0;
  373.                                 state = RGETDATA;
  374.                                 break;
  375.                         }
  376.                         break;
  377.                 }
  378.                 break;
  379.             case RGETDATA:    /* Wait for next data byte */
  380.                 message = EmptyStr;
  381.                 err = ReadMaskedByte(&c, &masked);
  382.                 switch (err) {
  383.                     case TIMEOUT:
  384.                     case CANCEL:
  385.                         message = MyString(STR_P, P_TIMEOUT);
  386.                         state = RTIMEDOUT;
  387.                         break;
  388.                     case FINE:
  389.                         cks = DoChecksum(c, cks);
  390.                         if (c == ETX && !masked)
  391.                             state = RGETCHECKSUM;
  392.                         else
  393.                             RBuffer[n++] = c;
  394.                         break;
  395.                 }
  396.                 break;
  397.             case RGETCHECKSUM:    /* Wait for checksum, or CRC */
  398.                 message = EmptyStr;
  399.                 err = ReadMaskedByte(&c, &masked);
  400.                 switch (err) {
  401.                     case TIMEOUT:
  402.                     case CANCEL:
  403.                         message = MyString(STR_P, P_TIMEOUT);
  404.                         state = RTIMEDOUT;
  405.                         break;
  406.                     case FINE:
  407.                         if (QuickB && UseCRC) {
  408.                             cks = UpdateCRC(c, cks);
  409.                             err = ReadMaskedByte(&c, &masked);
  410.                             switch (err) {
  411.                                 case TIMEOUT:
  412.                                 case CANCEL:
  413.                                     newcks = cks ^ 0xFF;
  414.                                     break;
  415.                                 case FINE:
  416.                                     cks = UpdateCRC(c, cks);
  417.                                     newcks = 0;
  418.                                     break;
  419.                             }
  420.                         } else
  421.                             newcks = c;
  422.                         if (newcks != cks) {
  423.                             message = MyString(STR_P, P_CRCERR);
  424.                             state = RTIMEDOUT;
  425.                         } else if (RBuffer[0] == 'F')
  426.                             state = RSUCCESS;
  427.                         else if (blocknum == SeqNum)
  428.                             state = RSENDACK;
  429.                         else if (blocknum != nextseq) {
  430.                             message = MyString(STR_P, P_BLOCKERR2);
  431.                             state = RTIMEDOUT;
  432.                         } else
  433.                             state = RSUCCESS;
  434.                         break;
  435.                 }
  436.                 break;
  437.             case RTIMEDOUT:        /* Send NAK */
  438.                 ++errors;
  439.                 UpdateProgress(Mark,Eof,TIME,Blk,errors,message);
  440.                 if (errors > MAXERRORS || fromsendpacket)
  441.                     return TIMEOUT;
  442.                 SendByte(NAK);
  443.                 state = RGETDLE;
  444.                 break;
  445.             case RSENDACK:        /* Send ACK */
  446.                 SendACK(SeqNum);
  447.                 state = RGETDLE;
  448.                 break;
  449.             case RSUCCESS:        /* Success */
  450.                 UpdateProgress(Mark,Eof,TIME,Blk,errors,
  451.                     MyString(STR_P,P_VERIFY));
  452.                 SeqNum = blocknum;
  453.                 Rsize = n;
  454.                 return FINE;
  455.         }
  456.     }
  457. }
  458.  
  459. /* ----- Wait until the SABuf indicated by AckSA has been ACKed -------- */
  460.  
  461. enum {            /* Send states */
  462.     SGETDLE,
  463.     SGETNUM,
  464.     SHAVEACK,
  465.     SGETPACKET,
  466.     STIMEDOUT,
  467.     SSENDNAK,
  468.     SSENDENQ,
  469.     SSENDDATA
  470. };
  471.  
  472. static short GetACK(void)
  473. {
  474.     register short state, err, errors;
  475.     short blocknum;
  476.     Boolean SentENQ;
  477.     short SAIndex;
  478.     Byte c;
  479.  
  480.     errors = 0;
  481.     SentENQ = FALSE;
  482.     state = SGETDLE;
  483.     for (;;) {
  484.         switch (state) {
  485.             case SGETDLE:    /* Wait for DLE */
  486.                 err = ReadByte(&c);
  487.                 if (CheckCancel())
  488.                     err = CANCEL;
  489.                 switch (err) {
  490.                     case CANCEL:
  491.                         if (!Aborting) {
  492.                             SendFailure('A');
  493.                             return err;
  494.                         }
  495.                         /* Fall thru to TIMEOUT */
  496.                     case TIMEOUT:
  497.                         state = STIMEDOUT;
  498.                         break;
  499.                     case FINE:
  500.                         switch (c) {
  501.                             case DLE:
  502.                                 state = SGETNUM;
  503.                                 break;
  504.                             case NAK:
  505.                                 ++errors;
  506.                                 UpdateProgress(Mark,Eof,TIME,Blk,errors,
  507.                                     MyString(STR_P,P_REPEAT));
  508.                                 if (errors > MAXERRORS)
  509.                                     return TIMEOUT;
  510.                                 state = SSENDENQ;
  511.                                 break;
  512.                             case ETX:
  513.                                 state = SSENDNAK;
  514.                                 break;
  515.                         }
  516.                         break;
  517.                 }
  518.                 break;
  519.             case SGETNUM:    /* Get block sequence number */
  520.                 err = ReadByte(&c);
  521.                 switch (err) {
  522.                     case TIMEOUT:
  523.                     case CANCEL:
  524.                         state = STIMEDOUT;
  525.                         break;
  526.                     case FINE:
  527.                         switch (c) {
  528.                             case 'B':
  529.                                 state = SGETPACKET;
  530.                                 break;
  531.                             case NAK:
  532.                                 ++errors;
  533.                                 UpdateProgress(Mark,Eof,TIME,Blk,errors,
  534.                                     MyString(STR_P,P_REPEAT));
  535.                                 if (errors > MAXERRORS)
  536.                                     return TIMEOUT;
  537.                                 state = SSENDENQ;
  538.                                 break;
  539.                             default:
  540.                                 state = (c >= '0' && c <= '9') ?
  541.                                     SHAVEACK : STIMEDOUT;
  542.                         }
  543.                 }
  544.                 break;
  545.             case SGETPACKET:    /* Get packet */
  546.                 if (!(err = ReadPacket(TRUE, TRUE))) {
  547.                     if (RBuffer[0] == 'F') {
  548.                         SendACK(SeqNum);
  549.                         return CANCEL;
  550.                     }
  551.                     return FINE;
  552.                 }
  553.                 state = STIMEDOUT;
  554.                 break;
  555.             case SHAVEACK:
  556.                 blocknum = c - '0';
  557.                 if (SABuf[AckSA].seq == blocknum) {
  558.                     UpdateProgress(Mark,Eof,TIME,Blk,errors,
  559.                         MyString(STR_P,P_VERIFY));
  560.                     AckSA = IncrSA(AckSA);
  561.                     --SAWaiting;
  562.                     return FINE;
  563.                 }
  564.                 if (SABuf[IncrSA(AckSA)].seq == blocknum && SAWaiting == 2) {
  565.                     UpdateProgress(Mark,Eof,TIME,Blk,errors,
  566.                         MyString(STR_P,P_VERIFY));
  567.                     AckSA = IncrSA(AckSA);
  568.                     AckSA = IncrSA(AckSA);
  569.                     SAWaiting -= 2;
  570.                     return FINE;
  571.                 }
  572.                 UpdateProgress(Mark,Eof,TIME,Blk,errors,
  573.                     MyString(STR_P,P_BLOCKERR2));
  574.                 if (SABuf[AckSA].seq == IncrSeq(blocknum))
  575.                     state = SentENQ ? SSENDDATA : SGETDLE;
  576.                 else
  577.                     state = Aborting ? SGETDLE : STIMEDOUT;
  578.                 SentENQ = FALSE;
  579.                 break;
  580.             case STIMEDOUT:
  581.                 ++errors;
  582.                 UpdateProgress(Mark,Eof,TIME,Blk,errors,
  583.                     MyString(STR_P,P_TIMEOUT));
  584.                 if (errors > MAXERRORS || (Aborting && errors > MAXABORT))
  585.                     return TIMEOUT;
  586.                 state = SSENDENQ;
  587.                 break;
  588.             case SSENDNAK:
  589.                 ++errors;
  590.                 if (errors > MAXERRORS)
  591.                     return TIMEOUT;
  592.                 SendByte(NAK);
  593.                 state = SGETDLE;
  594.                 break;
  595.             case SSENDENQ:
  596.                 ++errors;
  597.                 if (errors > MAXERRORS)
  598.                     return TIMEOUT;
  599.                 state = (ReSync(&c)) ? SSENDENQ : SHAVEACK;
  600.                 SentENQ = TRUE;
  601.                 break;
  602.             case SSENDDATA:
  603.                 SAIndex = AckSA;
  604.                 for (err = 1; err <= SAWaiting; ++err) {
  605.                     SendData(SAIndex);
  606.                     SAIndex = IncrSA(SAIndex);
  607.                 }
  608.                 state = SGETDLE;
  609.                 SentENQ = FALSE;
  610.                 break;
  611.         }
  612.     }
  613. }
  614.  
  615. /* ----- Send a packet to the host ------------------------------------- */
  616.  
  617. static short SendPacket(register short size)
  618. {
  619.     register PACKET *p;
  620.     register short err;
  621.  
  622.     if (SAWaiting == SAMax && (err = GetACK()))
  623.         return err;
  624.     SeqNum = IncrSeq(SeqNum);
  625.     p = &SABuf[FillSA];
  626.     p->seq = SeqNum;
  627.     p->num = size;
  628.     SendData(FillSA);
  629.     FillSA = IncrSA(FillSA);
  630.     ++SAWaiting;
  631.     return FINE;
  632. }
  633.  
  634. /* ----- Get host's ACKs on outstanding packets ------------------------ */
  635.  
  636. static short SAFlush(void)
  637. {
  638.     register short err;
  639.  
  640.     while (SAWaiting > 0)
  641.         if (err = GetACK())
  642.             return err;
  643.     return FINE;
  644. }
  645.  
  646. /* ----- Send a failure packet to the host ----------------------------- */
  647.  
  648. static void SendFailure(register Byte code)
  649. {
  650.     register Byte *p;
  651.  
  652.     AckSA = 0;
  653.     FillSA = 0;
  654.     SAWaiting = 0;
  655.     Aborting = TRUE;        /* Inform GetACK we're aborting */
  656.     p = SABuf[0].buf;
  657.     p[0] = 'F';
  658.     p[1] = code;
  659.     if (!SendPacket(2))
  660.         SAFlush();            /* Gotta wait for the host to ACK it */
  661. }
  662.  
  663. /* ----- Make info string for progress dialog -------------------------- */
  664.  
  665. static void MakeInfo(
  666.     register short id,                /* P_UPLOAD or P_DOWNLOAD */
  667.     register short vers)            /* MacBinary version */
  668. {
  669.     register Byte *p;
  670.     Byte s[256];
  671.  
  672.     p = MyString(STR_P, id);
  673.     memcpy(s, p, p[0] + 1);
  674.     if (QuickB) {
  675.         Append(s, MyString(STR_P, P_QUICKB));
  676.         if (UseCRC)
  677.             Append(s, MyString(STR_P, P_CRC));
  678.         if (Our.ws)
  679.             Append(s, MyString(STR_P, P_SENDAHEAD));
  680.     }
  681.     switch(vers) {
  682.         case 0:
  683.             Append(s, MyString(STR_P, P_TEXT));
  684.             break;
  685.         case 1:
  686.             Append(s, MyString(STR_P, P_BINARY1));
  687.             break;
  688.         case 2:
  689.             Append(s, MyString(STR_P, P_BINARY2));
  690.             break;
  691.     }
  692.     InfoProgress(s);
  693. }
  694.  
  695. /* ----- Download the specified file from the host --------------------- */
  696.  
  697. static short ReceiveFile(
  698.     Byte *name,
  699.     short volume,
  700.     long directory)
  701. {
  702.     register short err;
  703.     register short n;
  704.     register short headerLength = 0;/* Number of bytes in header */
  705.     Byte header[BinHeaderLength];    /* The first 128 bytes received */
  706.     short ref = 0;
  707.     long count;                        /* Number of bytes to write to file */
  708.     Byte name2[64];                    /* Name from MacBinary header */
  709.     long df, rf;                    /* Data fork, resource fork length */
  710.     Byte *usedName;                    /* File name used */
  711.  
  712.     UpdateProgress(0,0,0,0,0,EmptyStr);
  713.     SendACK(SeqNum);
  714.     for (;;) {
  715.         if (err = ReadPacket(FALSE, FALSE))
  716.             break;            /* Receive error */
  717.         switch (RBuffer[0]) {
  718.             case 'N':            /* Data packet */
  719.                 count = Rsize - 1;
  720.                 Mark += count;
  721.                 Blk++;
  722.                 if (headerLength < sizeof(header)) {
  723.                     n = MIN(count, sizeof(header) - headerLength);
  724.                     memcpy(header + headerLength, RBuffer + 1, n);
  725.                     headerLength += n;
  726.                     if (headerLength == sizeof(header)) {
  727.                         /* The header is complete. Try to use the file    */
  728.                         /* name from the MacBinary header. If this file    */
  729.                         /* exists already use the first name.            */
  730.                         if (Settings.Binary)        /* MacBinary check */
  731.                             Vers = BinCheckHeader(header, name2, &df, &rf);
  732.                         if (Vers) {
  733.                             err = CreateFile(volume, directory,
  734.                                 usedName = name2, 
  735.                                 Settings.binCreator, Settings.binType);
  736.                             if (err == dupFNErr)
  737.                                 err = CreateFile(volume, directory,
  738.                                     usedName = name,  
  739.                                     Settings.binCreator, Settings.binType);
  740.                         } else
  741.                             err = CreateFile(volume, directory,
  742.                                     usedName = name, 
  743.                                     Settings.binCreator, Settings.binType);
  744.                         if (err) {
  745.                             SendFailure('E');
  746.                             goto done;            /* Create error */
  747.                         }
  748.                         if (Vers) {                /* Valid MacBinary */
  749.                             NameProgress(usedName);
  750.                             if (err = BinOpenWrite(volume, directory,
  751.                                     usedName, header)) {
  752.                                 SendFailure('E');
  753.                                 goto done;        /* Open error */
  754.                             }
  755.                             ref = 1;            /* File is open */
  756.                             BinGetEOF(&Eof);
  757.                             /* Skip MacBinary header, write the rest */
  758.                             if (count -= n)
  759.                                 err = BinWrite(&count, RBuffer + 1 + n);
  760.                         } else {                /* Not MacBinary */
  761.                             if (err = OpenFile(volume, directory,
  762.                                     usedName, &ref)) {
  763.                                 SendFailure('E');
  764.                                 goto done;        /* Open error */
  765.                             }
  766.                             /* The first 128 bytes are no MB header,    */
  767.                             /* so they must be written as data block    */
  768.                             err = FSWrite(ref, &count, RBuffer + 1);
  769.                         }
  770.                         MakeInfo(P_DOWNLOAD, Vers);
  771.                     }
  772.                 } else                    /* Not the first 128 bytes */
  773.                     err = WRITE(count, RBuffer + 1);
  774.                 if (err) {
  775.                     SendFailure('E');
  776.                     goto done;            /* Disk write error */
  777.                 }
  778.                 SendACK(SeqNum);
  779.                 break;
  780.             case 'T':            /* Transfer packet */
  781.                 if (RBuffer[1] == 'C') {        /* Close file */
  782.                     SendACK(SeqNum);
  783.                     err = 0;
  784.                 } else {
  785.                     /* Unexpected "T" packet. Something is rotten    */
  786.                     /* on the other end. Send a failure packet to    */
  787.                     /* kill the transfer cleanly.                    */
  788.                     SendFailure('E');
  789.                     err = 3;
  790.                 }
  791.                 goto done;
  792.             case 'F':            /* Failure packet */
  793.                 SendACK(SeqNum);
  794.                 err = 4;
  795.                 goto done;
  796.         }
  797.     }
  798. done:
  799.     if (ref) {                    /* Close file if necessary */
  800.         CLOSEW;
  801.     }
  802.     return err;
  803. }
  804.  
  805. /* ----- Send the specified file to the host --------------------------- */
  806.  
  807. static short SendFile(
  808.     Byte *name,
  809.     short volume,
  810.     long directory)
  811. {
  812.     register Byte *p;
  813.     register short err;
  814.     short ref;
  815.     long n;
  816.     OSType creator, type;
  817.     long create, modif;
  818.  
  819.     /* Only send non-TEXT files as MacBinary if requested */
  820.  
  821.     Vers = (Binary && Settings.Binary &&
  822.         !InfoFile(volume, directory, name,
  823.             &creator, &type, &create, &modif) &&
  824.         type != TEXT) ? 2 : 0;
  825.     if (err = OPENR(volume, directory, name)) {
  826.         SendFailure('E');
  827.         return err;                /* Open error */
  828.     }
  829.     MakeInfo(P_UPLOAD, Vers);
  830.     GETEOF;
  831.     UpdateProgress(0,Eof,0,0,0,EmptyStr);
  832.  
  833.     do {
  834.         p = SABuf[FillSA].buf;
  835.         p[0] = 'N';
  836.         n = BufferSize - 1;
  837.         err = READ(n, &p[1]);
  838.         Mark += n;
  839.         Blk++;
  840.         if (err = eofErr)
  841.             err = 0;
  842.         if (err) {                /* Disk read error */
  843.             SendFailure('E');
  844.             CLOSER;
  845.             return err;
  846.         }
  847.         if (n > 0 && (err = SendPacket(n + 1))) {
  848.             CLOSER;
  849.             return err;
  850.         }
  851.     } while (n > 0);
  852.     CLOSER;
  853.  
  854.     /* Inform host that the file was sent */
  855.  
  856.     p = SABuf[FillSA].buf;
  857.     p[0] = 'T';
  858.     p[1] = 'C';
  859.     if (err = SendPacket(2))
  860.         return err;
  861.     return SAFlush();
  862. }
  863.  
  864. /* ----- Handle T packet ----------------------------------------------- */
  865.  
  866. static short TransferFile(void)
  867. {
  868.     register short err;
  869.     register Byte name[64];
  870.  
  871.     if ((RBuffer[1] != 'D' && RBuffer[1] != 'U') ||
  872.             (RBuffer[2] != 'A' && RBuffer[2] != 'B')) {
  873.         NameProgress((Byte *)"\p<wrong>");
  874.         SendFailure('N');    /* Wrong direction or file type */
  875.         return 1;
  876.     }
  877.  
  878.     /* Extract file type and name */
  879.  
  880.     Binary = (RBuffer[2] == 'B');
  881.     name[0] = (Rsize - 3 > 63) ? 63 : Rsize - 3;
  882.     memcpy(name + 1, RBuffer + 3, name[0]);
  883.     NameProgress(name);
  884.  
  885.     /* Do the transfer */
  886.  
  887.     err = (RBuffer[1] == 'U') ?
  888.         SendFile(name, Settings.volume, Settings.directory) :
  889.         ReceiveFile(name, Settings.volume, Settings.directory);
  890.     return err;
  891. }
  892.  
  893. /* ----- Called when a + packet is received ---------------------------- */
  894.  
  895. /*
  896.     Compuserve sends the following packet:
  897.     DLE 'B' '1' '+'
  898.     DLE 41            01 = window send
  899.     DLE 41            01 = window receive
  900.     DLE 48            08 = buffer size
  901.     DLE 41            01 = check method
  902.  
  903.     DLE 43            03 = dq
  904.     DLE 40            00 = no transport layer
  905.  
  906.     DLE 54            14 = Quote set    --- --- --- ETX --- ENQ --- ---
  907.     DLE 40            00                --- --- --- --- --- --- --- ---
  908.     D4                D4                DLE XON --- XOF --- NAK --- ---
  909.     DLE 40            00                --- --- --- --- --- --- --- ---
  910.     DLE 40            00                --- --- --- --- --- --- --- ---
  911.     DLE 40            00                --- --- --- --- --- --- --- ---
  912.     DLE 40            00                --- --- --- --- --- --- --- ---
  913.     DLE 40            00                --- --- --- --- --- --- --- ---
  914.  
  915.     DLE 42            02 = download resume (2 = auto)
  916.     DLE 40            00 = upload recovery
  917.     DLE 41            01 = file information
  918.     ETX 3D
  919. */
  920.  
  921. static short TransportParameters(void)
  922. {
  923.     register Byte *p;
  924.     register short err;
  925.  
  926.     His.ws = RBuffer[1];
  927.     His.wr = RBuffer[2];
  928.     His.bs = RBuffer[3];
  929.     His.cm = RBuffer[4];
  930.     p = SABuf[FillSA].buf;
  931.     p[0] = '+';
  932.     p[1] = DEFWS;
  933.     p[2] = DEFWR;
  934.     p[3] = DEFBS;
  935.     p[4] = DEFCM;
  936.     p[5] = DEFDQ;
  937.     if (err = SendPacket(6))
  938.         return err;
  939.     if (err = SAFlush())
  940.         return err;
  941.     Our.wr = MIN(His.ws, DEFWR);
  942.     Our.ws = MIN(His.wr, DEFWS);
  943.     Our.bs = MIN(His.bs, DEFBS);
  944.     Our.cm = MIN(His.cm, DEFCM);
  945.     if (!Our.bs)
  946.         Our.bs = 4;
  947.     BufferSize = Our.bs * 128;
  948.     QuickB = TRUE;
  949.     if (Our.cm == 1)
  950.         UseCRC = TRUE;
  951.     if (Our.ws) {
  952.         SAEnabled = TRUE;
  953.         SAMax = MAXSA;
  954.     }
  955.     return FINE;
  956. }
  957.  
  958. /* ----- Called when a ? packet is received ---------------------------- */
  959.  
  960. /* Note: never received such a packet */
  961.  
  962. static short ApplicationParameters(void)
  963. {
  964.     register Byte *p;
  965.     register short err;
  966.  
  967.     p = SABuf[FillSA].buf;
  968.     p[0] = '?';
  969.     p[1] = 1;
  970.     if (err = SendPacket(2))
  971.         return err;
  972.     return SAFlush();
  973. }
  974.  
  975. /* ----- Sleep a while ------------------------------------------------- */
  976.  
  977. static void Sleep(register unsigned long sec)
  978. {
  979.     register unsigned long start = Time;
  980.  
  981.     while((Time - start) < sec)
  982.         CheckCancel();
  983. }
  984.  
  985. /* ----- Intercept characters received for QuickB protocol ------------- */
  986.  
  987. void CisB(void)
  988. {
  989.     register short err;
  990.     static Byte enquiry[] = {    /* Answer if ENQ received */
  991.         DLE, '+', DLE, '0'
  992.     };
  993.  
  994.     /* Come here if ENQ was received */
  995.  
  996.     while (Busy)
  997.         ;
  998.     Sleep(ENQDELAY);
  999.     SerialSend(enquiry, sizeof(enquiry), &Busy);
  1000.     while (Busy)
  1001.         ;
  1002.  
  1003.     /* Set up defaults */
  1004.  
  1005.     SeqNum = 0;
  1006.     BufferSize = DEFBUFSIZE;
  1007.     QuickB = UseCRC = SAEnabled = FALSE;
  1008.     SAMax = 1;
  1009.  
  1010.     /* Go into B-protocol mode */
  1011.  
  1012.     SerialBinary(Settings.portSetup);
  1013.     if (Settings.handshake == 1)    /* XON/OFF must be off */
  1014.         SerialHandshake(0);
  1015.     Transfer = Transfer_B;
  1016.     DrawProgressDialog(P_CISB, EmptyStr);
  1017.     AckSA = FillSA = SAWaiting = 0;
  1018.     Aborting = FALSE;
  1019.     Mark = Blk = Eof = 0;
  1020.     Vers = 0;
  1021.     Ctime = Time;
  1022.  
  1023.     do {
  1024.         if (err = ReadPacket(FALSE, FALSE))
  1025.             break;
  1026.         switch (RBuffer[0]) {
  1027.             case 'T':            /* File transfer */
  1028.                 err = TransferFile();
  1029.                 Ctime = Time - Ctime;
  1030.                 Statistics(Mark, Ctime, err);
  1031.                 err = 1;
  1032.                 break;
  1033.             case '+':            /* Transport parameters packet */
  1034.                 NameProgress((Byte *)"\p<+>");
  1035.                 err = TransportParameters();
  1036.                 break;
  1037.             case '?':            /* Application parameters packet */
  1038.                 NameProgress((Byte *)"\p<?>");
  1039.                 err = ApplicationParameters();
  1040.                 break;
  1041.             default:            /* Unkown packet */
  1042.                 NameProgress((Byte *)"\p<unkown>");
  1043.                 SendFailure('E');
  1044.                 err = 1;
  1045.         }
  1046.     } while (!err);
  1047.  
  1048.     RemoveCancelDialog();
  1049.     Transfer = 0;
  1050.     SerialReset(Settings.portSetup);
  1051.     SerialHandshake(Settings.handshake);
  1052. }
  1053.